using System.Collections.Generic;
using System.Linq;
using FwkLight.Domain;

namespace FwkLight.CodeExtensions
{
  public static class EnumerableExtensionGateway
  {
    public static void VisitAllItemsUsing<T> ( this IEnumerable<T> items, IVisitor<T> visitor )
    {
      new EnumerableActions<T>(items).VisitAllItemsUsing(visitor);
    }

    public static Result GetResultOfVisitingAllItemsWith<T, Result> ( this IEnumerable<T> items, IValueReturningVisitor<Result, T> visitor )
    {
      return new EnumerableActions<T>(items).GetResultOfVisitingAllItemsWith(visitor);
    }

    public static IEnumerable<T> AllSatisfying<T> ( this IEnumerable<T> items, ISpecification<T> specification )
    {
      return new EnumerableActions<T>(items).AllMatching(specification).ToList();
    }

    public static IEnumerable<T> AllSatisfying<T, Param1>(this IEnumerable<T> items, ISpecification<T, Param1> specification, Param1 param1)
    {
      return new EnumerableActions<T, Param1>(items).AllMatching(specification, param1).ToList();
    }

    public static IEnumerable<T> AllSatisfying<T, Param1, Param2>(this IEnumerable<T> items, ISpecification<T, Param1, Param2> specification, Param1 param1, Param2 param2)
    {
      return new EnumerableActions<T, Param1, Param2>(items).AllMatching(specification, param1, param2).ToList();
    }

    public static IEnumerable<T> AllSatisfying<T, Param1, Param2, Param3>(this IEnumerable<T> items, ISpecification<T, Param1, Param2, Param3> specification, Param1 param1, Param2 param2, Param3 param3)
    {
      return new EnumerableActions<T, Param1, Param2, Param3>(items).AllMatching(specification, param1, param2, param3).ToList();
    }

    public static IEnumerable<T> AllSatisfying<T, Param1, Param2, Param3, Param4>(this IEnumerable<T> items, ISpecification<T, Param1, Param2, Param3, Param4> specification, Param1 param1, Param2 param2, Param3 param3, Param4 param4)
    {
      return new EnumerableActions<T, Param1, Param2, Param3, Param4>(items).AllMatching(specification, param1, param2, param3, param4).ToList();
    }

    public static IEnumerable<T> WhichAre<T> ( this IEnumerable<T> items, ISpecification<T> specification )
    {
      return new EnumerableActions<T>(items).AllMatching(specification).ToList();
    }

		public static IEnumerable<T> WhichAre<T, Param1>(this IEnumerable<T> items, ISpecification<T, Param1> specification, Param1 param1)
		{
			return new EnumerableActions<T, Param1>(items).AllMatching(specification, param1).ToList();
		}

		public static IEnumerable<T> WhichAre<T, Param1, Param2>(this IEnumerable<T> items, ISpecification<T, Param1, Param2> specification, Param1 param1, Param2 param2)
		{
			return new EnumerableActions<T, Param1, Param2>(items).AllMatching(specification, param1, param2).ToList();
		}

		public static IEnumerable<T> WhichAre<T, Param1, Param2, Param3>(this IEnumerable<T> items, ISpecification<T, Param1, Param2, Param3> specification, Param1 param1, Param2 param2, Param3 param3)
		{
			return new EnumerableActions<T, Param1, Param2, Param3>(items).AllMatching(specification, param1, param2, param3).ToList();
		}

		public static IEnumerable<T> WhichAre<T, Param1, Param2, Param3, Param4>(this IEnumerable<T> items, ISpecification<T, Param1, Param2, Param3, Param4> specification, Param1 param1, Param2 param2, Param3 param3, Param4 param4)
		{
			return new EnumerableActions<T, Param1, Param2, Param3, Param4>(items).AllMatching(specification, param1, param2, param3, param4).ToList();
		}

    public static IEnumerable<T> WhichCan<T> ( this IEnumerable<T> items, ISpecification<T> specification )
    {
      return new EnumerableActions<T>(items).AllMatching(specification).ToList();
    }

		public static IEnumerable<T> WhichCan<T, Param1>(this IEnumerable<T> items, ISpecification<T, Param1> specification, Param1 param1)
		{
			return new EnumerableActions<T, Param1>(items).AllMatching(specification, param1).ToList();
		}

    public static IEnumerable<T> WhichCan<T, Param1, Param2>(this IEnumerable<T> items, ISpecification<T, Param1, Param2> specification, Param1 param1, Param2 param2)
    {
      return new EnumerableActions<T, Param1, Param2>(items).AllMatching(specification, param1, param2).ToList();
    }

    public static IEnumerable<T> WhichCan<T, Param1, Param2, Param3>(this IEnumerable<T> items, ISpecification<T, Param1, Param2, Param3> specification, Param1 param1, Param2 param2, Param3 param3)
    {
      return new EnumerableActions<T, Param1, Param2, Param3>(items).AllMatching(specification, param1, param2, param3).ToList();
    }

    public static IEnumerable<T> WhichCan<T, Param1, Param2, Param3, Param4>(this IEnumerable<T> items, ISpecification<T, Param1, Param2, Param3, Param4> specification, Param1 param1, Param2 param2, Param3 param3, Param4 param4)
    {
      return new EnumerableActions<T, Param1, Param2, Param3, Param4>(items).AllMatching(specification, param1, param2, param3, param4).ToList();
    }

		public static IEnumerable<T> WhichCanBe<T>(this IEnumerable<T> items, ISpecification<T> specification)
		{
			return new EnumerableActions<T>(items).AllMatching(specification).ToList();
		}

		public static IEnumerable<T> WhichCanBe<T, Param1>(this IEnumerable<T> items, ISpecification<T, Param1> specification, Param1 param1)
		{
			return new EnumerableActions<T, Param1>(items).AllMatching(specification, param1).ToList();
		}

    public static IEnumerable<T> WhichCanBe<T, Param1, Param2>(this IEnumerable<T> items, ISpecification<T, Param1, Param2> specification, Param1 param1, Param2 param2)
    {
      return new EnumerableActions<T, Param1, Param2>(items).AllMatching(specification, param1, param2).ToList();
    }

    public static IEnumerable<T> WhichCanBe<T, Param1, Param2, Param3>(this IEnumerable<T> items, ISpecification<T, Param1, Param2, Param3> specification, Param1 param1, Param2 param2, Param3 param3)
    {
      return new EnumerableActions<T, Param1, Param2, Param3>(items).AllMatching(specification, param1, param2, param3).ToList();
    }

    public static IEnumerable<T> WhichCanBe<T, Param1, Param2, Param3, Param4>(this IEnumerable<T> items, ISpecification<T, Param1, Param2, Param3, Param4> specification, Param1 param1, Param2 param2, Param3 param3, Param4 param4)
    {
      return new EnumerableActions<T, Param1, Param2, Param3, Param4>(items).AllMatching(specification, param1, param2, param3, param4).ToList();
    }

    public static IEnumerable<Output> MapAllUsing<T, Output> ( this IEnumerable<T> itemsToMap, IMapper<T, Output> mapper )
    {
      return new EnumerableActions<T>(itemsToMap).MapAllUsing(mapper).ToList();
    }

    public static Output MapUsing<T, Output> ( this T itemToMap, IMapper<T, Output> mapper )
    {
      return new EnumerableActions<T>(new List<T> { itemToMap }).MapAllUsing(mapper).First();
    }
  }
}